#include "usart.h"

static USART_InitTypeDef USART_InitStructure;
static NVIC_InitTypeDef NVIC_InitStructure;
static GPIO_InitTypeDef GPIO_InitStructure;

volatile uint8_t g_usart1_flag = 0;							//接收完毕标志位（0:未接收	1:已接收）
volatile uint8_t g_usart1_buf[USART1_BUF_RCV_MAX_SIZE + 1]; //接收数据数组
volatile uint8_t g_usart1_index = 0;						//接收数据下标

volatile uint8_t g_usart2_flag = 0;							//接收完毕标志位（0:未接收	1:已接收）
volatile uint8_t g_usart2_buf[USART2_BUF_RCV_MAX_SIZE + 1]; //接收数据
volatile uint8_t g_usart2_index = 0;						//接收数据下标

volatile uint8_t g_usart3_flag = 0;							//接收完毕标志位（0:未接收	1:已接收）
volatile uint8_t g_usart3_buf[USART3_BUF_RCV_MAX_SIZE + 1]; //接收数据
volatile uint8_t g_usart3_index = 0;						//接收数据下标

// 串口1配置（TX:PA9 	RX:PA10）
void USART1_Config(uint32_t baud)
{
	/* 1.打开时钟 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

	/* 2.连接复用功能引脚 */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

	/* 3.配置GPIO */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// 4.配置串口（与通信对方必须一致）
	USART_InitStructure.USART_BaudRate = baud;										// 波特率：由传参决定
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						// 数据位：8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;							// 停止位：1位
	USART_InitStructure.USART_Parity = USART_Parity_No;								// 无奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;					// 收发模式
	USART_Init(USART1, &USART_InitStructure);

	/* 5.配置中断 */
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* 6.使能串口 */
	USART_Cmd(USART1, ENABLE);

	/* 7.使能接收中断 */
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}

// 串口2初始化
void USART2_Config(uint32_t baud)
{
	/* 1.打开时钟 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

	/* 2.连接复用功能引脚 */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

	/* 3.配置GPIO */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// 4.配置串口（与通信对方必须一致）
	USART_InitStructure.USART_BaudRate = baud;										// 波特率：由传参决定
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						// 数据位：8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;							// 停止位：1位
	USART_InitStructure.USART_Parity = USART_Parity_No;								// 无奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;					// 收发模式
	USART_Init(USART2, &USART_InitStructure);

	/* 5.配置中断 */
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* 6.使能串口 */
	USART_Cmd(USART2, ENABLE);

	/* 7.使能接收中断 */
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
}

// 串口3配置（TX:PB10 	RX:PB11）
void USART3_Config(uint32_t baud)
{
	/* 1.打开时钟 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

	/* 2.连接复用功能引脚 */
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);

	/* 3.配置GPIO */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	// 4.配置串口（与通信对方必须一致）
	USART_InitStructure.USART_BaudRate = baud;										// 波特率：由传参决定
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						// 数据位：8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;							// 停止位：1位
	USART_InitStructure.USART_Parity = USART_Parity_No;								// 无奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;					// 收发模式
	USART_Init(USART3, &USART_InitStructure);

	/* 5.配置中断 */
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* 6.使能串口 */
	USART_Cmd(USART3, ENABLE);

	/* 7.使能接收中断 */
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
}

// 串口1发送字符串
void usart1_send_str(char *s)
{
	g_usart1_index = 0;
	while (*s != '\0')
	{
		// 发送字符，并等待发送完毕
		USART_SendData(USART1, *s++);
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
			;
	}
}

// 串口2发送字符串
void usart2_send_str(char *s)
{
	g_usart2_index = 0;
	while (*s != '\0')
	{
		// 发送字符，并等待发送完毕
		USART_SendData(USART2, *s++);
		while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
			;
	}
}

// 串口3发送字符串
void usart3_send_str(char *s)
{
	g_usart3_index = 0;
	USART3_DEBUG(s);
	while (*s != '\0')
	{
		// 发送字符，并等待发送完毕
		USART_SendData(USART3, *s++);
		while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET)
			;
	}
}

// 串口1中断服务函数（触发条件：串口1接收到数据）
void USART1_IRQHandler(void)
{
	uint8_t data;

	/* 接收到新数据 */
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		data = USART_ReceiveData(USART1);
		// 回发数据
		USART_SendData(USART1, data);
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
			;

		g_usart1_buf[g_usart1_index++] = data;
		if (data == USART1_BUF_RCV_CHAR ||
			g_usart1_index >= USART1_BUF_RCV_MAX_SIZE) // 接收完毕标志位置1
		{
			g_usart1_buf[g_usart1_index] = '\0'; //为保证数据安全，最后一位置"\0"
			g_usart1_flag = 1;
			//USART1_DEBUG((char *)g_usart1_buf);
		}
	}
}

// 串口2中断服务函数（触发条件：串口2接收到数据）
void USART2_IRQHandler(void)
{
	uint8_t data;

	/* 接收到新数据 */
	if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
	{
		data = USART_ReceiveData(USART2);
		// 回发数据
		//USART_SendData(USART2, data);
		//while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
		//	;

		g_usart2_buf[g_usart2_index++] = data;
		if (data == USART2_BUF_RCV_CHAR ||
			g_usart2_index >= USART2_BUF_RCV_MAX_SIZE) // 接收完毕标志位置1
		{
			g_usart2_buf[g_usart2_index] = '\0';
			g_usart2_flag = 1;
			USART2_DEBUG((char *)g_usart2_buf);
		}
	}
}

// 串口3中断服务函数（触发条件：串口3接收到数据）
void USART3_IRQHandler(void)
{
	uint8_t data;
	/* 接收到新数据 */
	if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
	{
		data = USART_ReceiveData(USART3);
		// 回发数据
		//USART_SendData(USART3, data);
		//while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET)
		//	;

		g_usart3_buf[g_usart3_index++] = data;
		if (data == USART3_BUF_RCV_CHAR ||
			g_usart3_index >= USART3_BUF_RCV_MAX_SIZE) // 接收完毕标志位置1
		{
			g_usart3_buf[g_usart3_index] = '\0';
			g_usart3_flag = 1;
			USART3_DEBUG((char *)g_usart3_buf);
		}
	}
}

int print_f(const char *fmt, ...)
{
	// 参考自 https://blog.csdn.net/yockie/article/details/52796842
	int n; // 写入字符个数
	va_list args;
	va_start(args, fmt);
	char print_buf[USART1_BUF_SEND_MAX_SIZE];
	n = vsnprintf(print_buf, USART1_BUF_SEND_MAX_SIZE, fmt, args);
	usart1_send_str(print_buf);
	return n;
}

int print_ln(const char *fmt, ...)
{
	int n; // 写入字符个数
	va_list args;
	va_start(args, fmt);
	char print_buf[USART1_BUF_SEND_MAX_SIZE];
	n = vsnprintf(print_buf, USART1_BUF_SEND_MAX_SIZE, fmt, args);
	usart1_send_str(print_buf);
	usart1_send_str("\r\n");
	return n;
}
